﻿using LinFu.DynamicProxy;
using log4net;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace SW.EF.Core
{    
    /// <summary>
    /// log4net日志提供类 
    /// </summary>
    public class Log4NetProvider : ILogProvider
    { 
        private ILog _logInfo = LogManager.GetLogger("InfoLogger");
        private ILog _logError = LogManager.GetLogger("ErrorLogger");

        public void LogInfo(InvocationInfo info, DateTime startTime, TimeSpan timeSpan)
        {
            var format = "{0}开始时间:{1}{0}方法名称:{2}{0}方法参数:{3}{0}方法耗时:{4}{0}";
            var methodName = info.TargetMethod.ReflectedType.FullName + "." + info.TargetMethod.Name;
            var methodArgs = info.Arguments.Count() == 0 ? "" : info.Arguments.Aggregate((a, b) => a + " |*| " + b);
            var costTime = string.Format("{0} 时 {1} 分 {2} 秒 {3} 毫秒", timeSpan.Hours, timeSpan.Minutes, timeSpan.Seconds, timeSpan.Milliseconds);
            ThreadPool.QueueUserWorkItem(delegate { _logInfo.Info(string.Format(format, Environment.NewLine, startTime, methodName, methodArgs, costTime)); });
        }

        public void LogError(InvocationInfo info, DateTime startTime, Exception e)
        {
            var format = "{0}开始时间:{1}{0}方法名称:{2}{0}方法参数:{3}{0}错误信息:{4}{0}错误源:{5}{0}堆栈跟踪:{6}{0}内部错误信息:{7}{0}内部错误源:{8}{0}内部错误堆栈:{9}{0}";
            var methodName = info.TargetMethod.ReflectedType.FullName + "." + info.TargetMethod.Name;
            var methodArgs = info.Arguments.Count() == 0 ? "" : info.Arguments.Aggregate((a, b) => a + " |*| " + b);
            var innerError = string.Empty;
            var innerSource = string.Empty;
            var innerStack = string.Empty;
            if (e.InnerException != null) {
                innerError = e.InnerException.Message;
                innerSource = e.InnerException.Source;
                innerStack = e.InnerException.StackTrace;
            }
            ThreadPool.QueueUserWorkItem(delegate { _logError.Error(string.Format(format, Environment.NewLine, startTime, methodName, methodArgs, e.Message, e.Source, e.StackTrace, innerError, innerSource, innerStack)); });
        }
    }
}
